package com.nsharmon.main;

import java.util.Locale;
import java.util.Set;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.criterion.Restrictions;

import com.nsharmon.dao.entity.Axiom;
import com.nsharmon.dao.entity.ComparisonAxiom.BlankThanVariant;
import com.nsharmon.dao.entity.ComparisonCondition;
import com.nsharmon.dao.entity.Condition;
import com.nsharmon.dao.entity.ConditionAxiom;
import com.nsharmon.dao.entity.ContainerAxiom;
import com.nsharmon.dao.entity.ContainerAxiom.ContainerVariant;
import com.nsharmon.dao.entity.EntityObject;
import com.nsharmon.dao.entity.EqualityAxiom;
import com.nsharmon.dao.entity.EqualityAxiom.EqualityVariant;
import com.nsharmon.dao.entity.ComparisonAxiom;
import com.nsharmon.dao.entity.ComparisonAxiom.GreaterThanVariant;
import com.nsharmon.dao.entity.ComparisonAxiom.LessThanVariant;
import com.nsharmon.dao.entity.Project;
import com.nsharmon.l18n.L18n;
import com.nsharmon.model.LogicManager;
import com.nsharmon.model.transformer.ComparisonTransformer;
import com.nsharmon.model.transformer.ConditionTransformer;
import com.nsharmon.model.transformer.ContainerTransformer;
import com.nsharmon.model.transformer.EqualityTransformer;

public class Main {
	public static void main(String[] args) {
		Configuration conf = new Configuration()
			.configure("hibernate.cfg.xml");
		
		conf.setProperty("hbm2ddl.auto", "create");
		
		@SuppressWarnings("deprecation")
		SessionFactory sessionFactory = conf.buildSessionFactory();
		
		Session session = sessionFactory.openSession();
		
		L18n.get().setLocale(Locale.ENGLISH);
		Project project = generateDatabase(session, "default");
		if(project != null) {
			LogicManager lm = new LogicManager(project);
			Set<Axiom> axioms = lm.getAxioms();
			for(Axiom axiom : axioms) {
				System.out.println(axiom.toString());
			}
			
			lm.addTransformer(new ContainerTransformer());
			lm.addTransformer(new EqualityTransformer());
			lm.addTransformer(new ComparisonTransformer());
			lm.addTransformer(new ConditionTransformer());
			
			System.out.println("\nGenerated axioms:");
			axioms = lm.getGeneratedAxioms();
			for(Axiom axiom : axioms) {
				System.out.println(axiom.toString());
			}			
		}
	}

	private static Project generateDatabase( Session session, String projectName ) {
		Project project = null;
		Transaction trx = session.beginTransaction();		
		try {
			project = (Project)session.createCriteria(Project.class)
				.add(Restrictions.eq("name", "default"))
				.uniqueResult();
			
			if(project == null) {
				project = new Project();
				project.setName("default");
				session.save(project);
			
				ContainerAxiom.contains(session, project, ContainerVariant.HasVariant, "Year", "Month");
				ContainerAxiom.contains(session, project, ContainerVariant.HasVariant, "Month", "Day");
				ContainerAxiom.contains(session, project, ContainerVariant.HasVariant, "Day", "Hour");
				EqualityAxiom.is(session, project, EqualityVariant.IsCalledVariant,  "Month", "Blue moon");
	
				ComparisonAxiom.isLessThan(session, project, LessThanVariant.IsLessThan, "John", "Sally");
				ComparisonAxiom.isBlankThan(session, project, BlankThanVariant.IsBlankThan, "Joe", "Sally", "smarter");
				ComparisonAxiom.isBlankThan(session, project, BlankThanVariant.IsBlankThan, "Sally", "Dolly", "smarter");
				ComparisonAxiom.asBlankAs(session, project, "Pink", "Sally", "smarter");
				
				Condition cond = ComparisonCondition.isBlankThan(session, BlankThanVariant.IsBlankThanOrEqualTo, "Joe", "Sally", "smarter");
				Axiom isCalledAxiom = new EqualityAxiom();
				isCalledAxiom.addEntity(session, "Joe");
				isCalledAxiom.addEntity(session, "Joe, the smart");
				isCalledAxiom.setVariant(EqualityVariant.IsCalledVariant);
				
				ConditionAxiom.ifThen(session, project, cond, isCalledAxiom, ConditionAxiom.ConditionVariant.Default);
			}
			trx.commit();
		} catch (HibernateException e) {
			project = null;
			trx.rollback();
			
			e.printStackTrace();
		} finally {
			session.close();
		}
		return project;
	}
}
